#include "NetUtils.h"

// 确保发送指定长度的数据。处理部分发送和 EINTR 信号中断。
ssize_t writen(int fd, const void *buf, size_t count) {
    size_t left = count;
    ssize_t written_len = 0;
    const char *p = (const char *)buf;

    while (left > 0) {
        if ((written_len = ::send(fd, p, left, 0)) <= 0) {
            if (written_len == -1 && errno == EINTR) {
                continue; // 被信号中断，继续
            }
            return -1; // 发生错误
        }
        left -= written_len;
        p += written_len;
    }
    return count;
}

// 确保读取指定长度的数据。处理部分读取和 EINTR 信号中断。
ssize_t readn(int fd, void *buf, size_t count) {
    size_t left = count;
    ssize_t read_len = 0;
    char *p = (char *)buf;

    while (left > 0) {
        if ((read_len = ::recv(fd, p, left, 0)) <= 0) {
            if (read_len == -1 && errno == EINTR) {
                continue;
            }
            // 返回实际读取的字节数，0 表示连接关闭，-1 表示错误
            return count - left; 
        }
        left -= read_len;
        p += read_len;
    }
    return count;
}

// 消息打包与发送。格式: [Tag(4B)] + [Length(4B)] + [Value(Length B)]
void sendMessage(int sockfd, int tag, const string& value) {
    // 准备数据
    int value_len = value.size(); 
    
    // 字节序转换（主机序 -> 网络序）
    uint32_t net_tag = htonl(tag);
    uint32_t net_len = htonl(value_len); 

    // 构造完整的发送缓冲区
    size_t total_size = 8 + value_len;
    std::vector<char> send_buffer(total_size);
    
    // 拷贝头部数据 (Tag, Length)
    std::memcpy(send_buffer.data(), &net_tag, 4);
    std::memcpy(send_buffer.data() + 4, &net_len, 4);
    
    // 拷贝消息体数据
    if (value_len > 0) {
        std::memcpy(send_buffer.data() + 8, value.c_str(), value_len);
    }
    
    // 发送完整的字节流
    if (writen(sockfd, send_buffer.data(), total_size) != (ssize_t)total_size) {
        cerr << "Error: Failed to send complete message." << endl;
    } else {
        // cout << "-> Send SUCCESS. Value: \"" << value << "\"" << endl;
    }
}

// 接收并解析完整的消息。
Message receiveMessage(int sockfd) {
    Message msg;
    char header_buf[8] = {0};
    
    // 读取头部
    ssize_t ret = readn(sockfd, header_buf, 8);
    if (ret != 8) {
        if (ret == 0) throw std::runtime_error("Connection closed by server.");
        throw std::runtime_error("Server header read incomplete or error.");
    }

    // 字节序转换与解析
    uint32_t net_tag, net_len;
    std::memcpy(&net_tag, header_buf, 4);
    std::memcpy(&net_len, header_buf + 4, 4);
    
    msg.tag = (int)ntohl(net_tag);
    msg.length = (int)ntohl(net_len);
    
    // 读取消息体
    if (msg.length < 0) {
        throw std::runtime_error("Received invalid negative message length.");
    }
    if (msg.length > 0) {
        msg.value.resize(msg.length); 
        // 将数据直接读入 string 内部缓冲区
        ret = readn(sockfd, &msg.value[0], msg.length); 
        if (ret != (ssize_t)msg.length) {
            throw std::runtime_error("Server body read incomplete.");
        }
    } else {
        msg.value = ""; // 长度为0时，value为空
    }
    
    return msg;
}

// 解析用户输入字符串为 Tag 和 Value。
bool parseInput(const string& input, int& tag, string& value) {
    std::stringstream ss(input);
    string tag_str;
    
    // 读取第一个参数 (Tag)
    if (!(ss >> tag_str)) {
        return false; // 输入为空
    }
    
    // 尝试将 Tag 转换为整数
    try {
        tag = std::stoi(tag_str);
    } catch (const std::exception&) {
        cerr << "Error: Invalid tag format. Must be an integer." << endl;
        return false;
    }

    // 读取剩余部分作为 Value
    // 找到第一个空格之后的位置
    size_t first_space = input.find(' ');
    if (first_space == string::npos || first_space + 1 >= input.length()) {
        // 如果没有空格，或者空格后没有内容
        value = "";
    } else {
        // 截取第一个空格之后的所有内容作为 value
        value = input.substr(first_space + 1);
    }

    return true;
}

// 清理无效的 UTF-8 字节序列。
string clean_query(const std::string& input_str) {
    std::string cleaned_str;
    try {
        // 使用 utf8::replace_invalid 尝试修复或替换无效字节
        utf8::replace_invalid(input_str.begin(), input_str.end(), 
                              std::back_inserter(cleaned_str));
    } catch (const std::exception& e) {
        // 如果清理过程中仍发生意外，返回原始输入并记录错误
        std::cerr << "Warning: UTF-8 replacement failed: " << e.what() << std::endl;
        return input_str; 
    }
    return cleaned_str;
}